﻿using System.Collections.Generic;

namespace Algorytm
{
    public class Algorytm_Nauczyciel
    {
        public int numer;
        public int liczba_przedmiotow;
        public int numer_preferowanej_sali;
        public int liczba_przedzialow_godzinowych;
        public List<Algorytm_Przedzial> przedzialy;
        public List<Algorytm_Przedzial> zle_przedzialy = new List<Algorytm_Przedzial>();
        public List<int> przedmioty;
        public List<Algorytm_Para_Studia> przedmioty_studia;
        private Algorytm_Element_Planu[][] tab;
        public int laczna_liczba_przedmiotow;
        public int laczna_dostepnosc;

        public Algorytm_Nauczyciel() { }

        public Algorytm_Nauczyciel(int _numer_nauczyciela, int _numer_preferowanej_sali, int _liczba_przedmiotow, List<Algorytm_Para_Studia> _tablica_przedmiotow, int _liczba_przedzialow_godzin, Algorytm_Przedzial[] _przedzialy)
        {
            Algorytm_Tworzenie_dla_Uczelni.p("konstruktor w Nauczyciel");
            laczna_liczba_przedmiotow = 0;
            tab = Algorytm_Tworzenie_dla_Uczelni.Init_tab();
            numer = _numer_nauczyciela;
            liczba_przedmiotow = _liczba_przedmiotow;
            numer_preferowanej_sali = _numer_preferowanej_sali;
            liczba_przedzialow_godzinowych = _liczba_przedzialow_godzin;
            przedzialy = new List<Algorytm_Przedzial>();
            przedmioty_studia = _tablica_przedmiotow;
            laczna_dostepnosc = 0;
            for (int i = 0; i < _przedzialy.Length; i++)
            {
                przedzialy.Add(_przedzialy[i]);
                laczna_dostepnosc += _przedzialy[i].Koniec - _przedzialy[i].Poczatek;
            }
        }

        public void Dodaj_zly_przedzial(Algorytm_Przedzial przedzial)
        {
            //Algorytm_Tworzenie_dla_Szkoly.p("dodaje zly w " + numer);
            zle_przedzialy.Add(przedzial);
        }

        public void Utworz_elementy_do_planu(int flaga)
        {
            if (flaga == 0)
            {
                tab = Algorytm_Tworzenie_dla_Szkoly.Init_tab();
            }
            else
            {
                tab = Algorytm_Tworzenie_dla_Uczelni.Init_tab();
            }
        }

        public Algorytm_Nauczyciel(int _numer_nauczyciela, int _numer_preferowanej_sali, int _liczba_przedmiotow, int[] _tablica_przedmiotow, int _liczba_przedzialow_godzin, Algorytm_Przedzial[] _przedzialy)
        {
            laczna_liczba_przedmiotow = 0;
            tab = Algorytm_Tworzenie_dla_Szkoly.Init_tab();
            przedzialy = new List<Algorytm_Przedzial>();
            przedmioty = new List<int>();
            numer = _numer_nauczyciela;
            liczba_przedmiotow = _liczba_przedmiotow;
            numer_preferowanej_sali = _numer_preferowanej_sali;
            liczba_przedzialow_godzinowych = _liczba_przedzialow_godzin;
            for (int i = 0; i < _tablica_przedmiotow.Length; i++)
            {
                przedmioty.Add(_tablica_przedmiotow[i]);
            }
            laczna_dostepnosc = 0;

            for (int i = 0; i < _przedzialy.Length; i++)
            {
                przedzialy.Add(_przedzialy[i]);
                //System.Console.WriteLine("dodaje " + (_przedzialy[i].Koniec - _przedzialy[i].Poczatek) + " i mam teraz " + laczna_dostepnosc);
                laczna_dostepnosc += _przedzialy[i].Koniec - _przedzialy[i].Poczatek;
            }
        }

        public void Zlicz_laczna_liczbe_godzin()
        {
            laczna_liczba_przedmiotow = 0;
            foreach (var item in przedmioty_studia)
            {
                laczna_liczba_przedmiotow += item.ilosc_wystapien;
            }
        }

        public bool czy_jest_dostepny(int dzien, int poczatek, int dlugosc)
        {
            bool value = false;

            foreach (var item in przedzialy)
            {
                if (item.Dzien == dzien && item.Poczatek <= poczatek && item.Koniec >= (poczatek + dlugosc))
                {
                    return true;
                }
            }
            return value;
        }

        public bool czy_uczy_przedmiotu(int numer)
        {
            return przedmioty.Contains(numer);
        }

        public void dodaj_do_planu_awaryjnego()
        {
            for (int i = 0; i < tab.Length; i++)
            {
                for (int j = 0; j < tab[i].Length; j++)
                {
                    if (tab[i][j].Czy_jest() && tab[i][j].czy_jest_z_awaryjnego)
                    {
                        Algorytm_Tworzenie_dla_Uczelni.wyniki.dodaj_element(numer, tab[i][j].nauczyciel, tab[i][j].przedmiot, tab[i][j].sala,
                            i, j, tab[i][j].dlugosc, tab[i][j].czy_grupowe);
                        if (tab[i][j].czy_jest_drugi_przedmiot)
                        {
                            Algorytm_Tworzenie_dla_Uczelni.wyniki.dodaj_element(numer, tab[i][j].drugi_przedmiot.nauczyciel, tab[i][j].drugi_przedmiot.przedmiot, tab[i][j].drugi_przedmiot.sala,
                            i, j, tab[i][j].drugi_przedmiot.dlugosc, true);
                        }
                    }
                }
            }
        }

        public bool czy_moze_miec_zajecia(int dzien, int godzina, int dlugosc, int zakres_dnia)
        {
            if (godzina + dlugosc > zakres_dnia) return false;
            for (int i = 0; i < dlugosc; i++)
            {
                if (tab[dzien][godzina + i].Czy_jest() || tab[dzien][godzina + i].czy_sa_fragmentem_zajec) return false;
            }
            return true;
        }

        public void Print()
        {
            Algorytm_Tworzenie_dla_Uczelni.p("druk dla " + numer);
            for (int i = 0; i < tab.Length; i++)
            {
                for (int j = 0; j < tab[i].Length; j++)
                {
                    tab[i][j].Print();
                }
            }
            Algorytm_Tworzenie_dla_Uczelni.p("po druku ");
        }

        public void Usun_skojarzenie(int dzien, int godzina)
        {
            tab[dzien][godzina].Usun();
        }

        public void Usun_skojarzenie(int dzien, int godzina, int dlugosc)
        {
            for (int i = 0; i < dlugosc; i++)
            {
                tab[dzien][godzina + i].Usun();
            }
        }

        public void Dodaj_skojarzenie(Algorytm_Element_Planu element, int dzien, int godzina)
        {
            tab[dzien][godzina] = element;
        }

        public void Dodaj_skojarzenie(Algorytm_Element_Planu element, int dzien, int godzina, int dlugosc)
        {
            tab[dzien][godzina] = element;
            Algorytm_Element_Planu el = new Algorytm_Element_Planu(element.klasa, element.nauczyciel, element.przedmiot, element.sala, element.dlugosc, element.czy_grupowe);
            for (int i = 1; i < dlugosc; i++)
            {
                tab[dzien][godzina + i] = el;
                tab[dzien][godzina + i].Dodaj_jako_fragment_zajec();
            }
        }

        public void Dodaj_skojarzenie_do_planu_awaryjnego(Algorytm_Element_Planu element, int dzien, int godzina, int dlugosc)
        {
            tab[dzien][godzina] = element;
            Algorytm_Element_Planu el = new Algorytm_Element_Planu(element.klasa, element.nauczyciel, element.przedmiot, element.sala, element.dlugosc, element.czy_grupowe);
            for (int i = 1; i < dlugosc; i++)
            {
                tab[dzien][godzina + i] = el;
                tab[dzien][godzina + i].Dodaj_jako_fragment_zajec();
            }
        }

        public int policz_priorytet(int dzien, int godzina)
        {
            //if (czy_ma_juz_jakies_zajecia(dzien, godzina)) return Algorytm.MIN_PRIO;
            int prio = 0;
            if (godzina > 0)
                if (tab[dzien][godzina - 1].klasa != -1) prio += 1;
            if (godzina + 1 < Algorytm_Tworzenie_dla_Szkoly.liczba_godzin_w_dniu)
                if (tab[dzien][godzina + 1].klasa != -1) prio += 1;
            return prio;
        }

        public int policz_priorytet(int dzien, int godzina, int dlugosc)
        {
            int prio = 0;
            if (godzina > 0)
                if (tab[dzien][godzina - 1].klasa != -1) prio += 1;
            if (godzina + dlugosc < Algorytm_Tworzenie_dla_Szkoly.liczba_godzin_w_dniu)
                if (tab[dzien][godzina + dlugosc].klasa != -1) prio += 1;
            return prio;
        }

        public List<Algorytm_Element_Planu> Zwroc_przedmioty_do_zamiany(int dzien)
        {
            List<Algorytm_Element_Planu> lista = new List<Algorytm_Element_Planu>();
            foreach (var item in zle_przedzialy)
            {
                if (item.Dzien != dzien) continue;
                if (tab[dzien][item.Poczatek].czy_sa_fragmentem_zajec)
                {
                    int q = item.Poczatek - 1;
                    while (tab[dzien][q].czy_sa_fragmentem_zajec) q--;
                    tab[dzien][q].Ustaw_dzien_i_godzine(dzien, q);
                    Algorytm_Element_Planu element = new Algorytm_Element_Planu(tab[dzien][q]);

                    lista.Add(element);
                }
                for (int i = item.Poczatek; i < item.Koniec; i++)
                {
                    if (tab[dzien][i].Czy_jest() && !tab[dzien][i].czy_sa_fragmentem_zajec)
                    {
                        tab[dzien][i].Ustaw_dzien_i_godzine(dzien, i);
                        Algorytm_Element_Planu element = new Algorytm_Element_Planu(tab[dzien][i]);

                        lista.Add(element);
                    }
                }
            }
            return lista;
        }

        public bool czy_ucze_tego_na_studiach(int _przedmiot)
        {
            bool czy = false;
            foreach (var item in przedmioty_studia)
            {
                if (item.numer == _przedmiot) return true;
            }
            return czy;
        }

        public bool sprawdz_czy_jest_w_zlym_przedziale(int dzien, int godzina, int dlugosc)
        {
            foreach (var item in zle_przedzialy)
            {
                if (item.Dzien == dzien)
                {
                    if (godzina < item.Koniec && godzina + dlugosc > item.Poczatek) return true;
                }
            }
            return false;
        }

        public bool czy_ma_juz_jakies_zajecia(int dzien, int godzina)
        {
            return tab[dzien][godzina].Czy_jest();
        }

        public int policz_priorytet_usuniecia(int dzien, int godzina)
        {
            int prio = 0;
            if (godzina > 0)
                if (tab[dzien][godzina - 1].klasa != -1) prio -= 1;
            if (godzina + 1 < Algorytm_Tworzenie_dla_Szkoly.liczba_godzin_w_dniu)
                if (tab[dzien][godzina + 1].klasa != -1) prio -= 1;
            if (prio != -2) return 0;
            return prio;
        }

        public int policz_priorytet_usuniecia(int dzien, int godzina, int dlugosc)
        {
            int prio = 0;
            if (godzina > 0)
                if (tab[dzien][godzina - 1].klasa != -1) prio -= 1;
            if (godzina + dlugosc < Algorytm_Tworzenie_dla_Szkoly.liczba_godzin_w_dniu)
                if (tab[dzien][godzina + dlugosc].klasa != -1) prio -= 1;
            if (prio != -2) return 0;
            return prio;
        }

        public void dodaj_do_planu()
        {
            for (int i = 0; i < tab.Length; i++)
            {
                for (int j = 0; j < tab[i].Length; j++)
                {
                    if (tab[i][j].Czy_jest() && !tab[i][j].czy_sa_fragmentem_zajec)
                    {
                        Algorytm_Tworzenie_dla_Uczelni.wyniki.dodaj_element(0, tab[i][j].nauczyciel, tab[i][j].przedmiot, tab[i][j].sala,
                            i, j, tab[i][j].dlugosc, tab[i][j].czy_grupowe);
                        if (tab[i][j].czy_jest_drugi_przedmiot)
                        {
                            Algorytm_Tworzenie_dla_Uczelni.wyniki.dodaj_element(0, tab[i][j].drugi_przedmiot.nauczyciel, tab[i][j].drugi_przedmiot.przedmiot, tab[i][j].drugi_przedmiot.sala,
                            i, j, tab[i][j].drugi_przedmiot.dlugosc, true);
                        }
                    }
                }
            }
        }
    }
}